
/**
 * @(#)MailServiceImpl.java 2017å¹´9æ28æ¥	ä¸å2:41:46 Copyrights (C) 2017é«å¾·ä¿¡æ¯ææ¯æéå¬å¸
 */
package com.wwy.monitor.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.mail.internet.InternetAddress;

import com.alibaba.alimonitor.jmonitor.utils.IPUtils;
import com.wwy.monitor.config.BulbEmailProperties;
import com.wwy.monitor.mapper.tddl.MonitorAlertMailMapper;
import com.wwy.monitor.model.constants.MailConts;
import com.wwy.monitor.model.enumeration.ExceptionCodeEnum;
import com.wwy.monitor.model.enumeration.MailEnum;
import com.wwy.monitor.model.param.MailMessageParam;
import com.wwy.monitor.model.tddl.dto.MonitorAlertMailDTO;
import com.wwy.monitor.model.vo.MailMessageVO;
import com.wwy.monitor.service.BaseService;
import com.wwy.monitor.util.McStringUtil;
import com.autonavi.dyui.common.exception.BizException;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;

import static java.lang.Boolean.TRUE;

/**
 * (ç±»ååè½è¯´ææè¿°)
 * <p>
 * ä¿®æ¹åå²:											<br>
 * ä¿®æ¹æ¥æ    		ä¿®æ¹äººå   	çæ¬	 		ä¿®æ¹åå®¹<br>
 * -------------------------------------------------<br>
 * 2017å¹´9æ28æ¥ ä¸å2:41:46   fulianqiu     1.0    	åå§ååå»º<br>
 * </p>
 *
 * @author fulianqiu
 * @version 1.0
 * @since JDK1.7
 */
@Service("mailMcService")
public class MailMcService extends BaseService {
    public static final Logger LOGGER = LoggerFactory.getLogger("mailJobLogger");
    @Autowired
    private BulbEmailProperties portalEmailProperties;
    @Autowired
    private JavaMailSender javaMailSender;
    @Autowired
    private MonitorAlertMailMapper mcMailMapper;
    private Integer pageSize = 2;

    public boolean sendMsg(String userId, MailMessageVO mailParam) {
//校验参数
        checkParam(mailParam);
        MailMessageParam mcMail = new MailMessageParam();
        mcMail.setToMails(str2List(mailParam.getToMailList()));
        mcMail.setCcMails(str2List(mailParam.getCcMailList()));
        mcMail.setMailTitle(mailParam.getMailTitle());
        mcMail.setMailText(mailParam.getMailText());
        return addMailToQueue(userId, mcMail);
    }

    /**
     * (åéé®ä»¶è¯·æ±åå¥æ°æ®åºéå)
     *
     * @param userId
     * @param mailMessageParam
     */
    public boolean addMailToQueue(String userId, MailMessageParam mailMessageParam) {
        LOGGER.info("mailå å¥éå,userId={}", userId);
        boolean result = false;
        try {
            MonitorAlertMailDTO mcMail = new MonitorAlertMailDTO();
            mcMail.setUserId(userId);
            mcMail.setToMails(mailMessageParam.getToMails());
            mcMail.setCcMails(mailMessageParam.getCcMails());
            mcMail.setMailTitle(mailMessageParam.getMailTitle());
            mcMail.setMailText(mailMessageParam.getMailText());
            mcMail.setFlag(MailEnum.Flag.UNHANDLE.getCode());
            mcMail.setStatus(MailEnum.Status.NORMAL.getCode());
            mcMail.setHostIp("");
            Date now = new Date();
            mcMail.setCreateTime(now);
            mcMail.setUpdateTime(now);
            mcMailMapper.insert(mcMail);
            result = true;
            LOGGER.info("mailå å¥éåæå,userId={}", userId);
        } catch (Exception e) {
            LOGGER.error(McStringUtil.join("å å¥éåå¤±è´¥", mailMessageParam.toString()), e);
            result = false;
        }
        return result;
    }

    /**
     * (æ¢å æ°æ®)
     */
    public void occupyData() {
        Date updateTime = new Date();
        int count = mcMailMapper.occupyData(MailEnum.Flag.UNHANDLE.getCode(), MailEnum.Flag.SENDING.getCode(), IPUtils.getLocalIp(),
                updateTime);
        LOGGER.info("occupyData count={}", count);
    }

    /**
     * (æ ¹æ®IPæ¥è¯¢åéä¸­çæ°æ®å¹¶åé)
     */
    public void queryAndSend() {
        List<MonitorAlertMailDTO> list = mcMailMapper.selectData(IPUtils.getLocalIp(), MailEnum.Flag.SENDING.getCode(), 0L, pageSize);
        LOGGER.info("queryAndSend list={}", list.size());
        Date now = new Date();
        if (CollectionUtils.isNotEmpty(list)) {
//å¹¶è¡å¤ç
            list.parallelStream().forEach(mcMail -> {
                try {
                    MailMessageVO mailMessageVO = new MailMessageVO();
                    mailMessageVO.setMailTitle(mcMail.getMailTitle());
                    mailMessageVO.setMailText(mcMail.getMailText());
//å¤çæ¥åè
                    if (!Strings.isNullOrEmpty(mcMail.getToMails())) {
                        List<String> toMailList = str2List(mcMail.getToMails());
                        mailMessageVO.setToMailList(toMailList);
                    }
//å¤çæéè
                    if (!Strings.isNullOrEmpty(mcMail.getCcMails())) {
                        List<String> ccMailList = str2List(mcMail.getCcMails());
                        mailMessageVO.setCcMailList(ccMailList);
                    }
//åéé®ä»¶
                    boolean flag = sendMail(mailMessageVO);
//åéæååï¼åæ´ç¶æ
                    if (flag) {
                        mcMailMapper.updateFlag(MailEnum.Flag.SENDING.getCode(), MailEnum.Flag.DONE.getCode(), mcMail.getId(), now);
                    }
                } catch (Exception e) {
                    LOGGER.error("åéemaiå¤±è´¥", e);
                    mcMailMapper.updateFlag(MailEnum.Flag.SENDING.getCode(), MailEnum.Flag.FAIL.getCode(), mcMail.getId(), now);
                }
            });
        }
    }

    /**
     * (å¤çå¤±è´¥çæ°æ®åé¿æ¶é´å¤äºåéä¸­çæ°æ®)
     */
    public void retrySend() {
        Date now = new Date();
//å°åºéçæ°æ®ç¶ææ¢å¤ææªå¤ç
        int retryFialSendCount = this.mcMailMapper.retryFailSend(MailEnum.Flag.FAIL.getCode(), MailEnum.Flag.UNHANDLE.getCode(), now);
        LOGGER.info("retryFialSendCount={}", retryFialSendCount);
//å¤çé¿æ¶é´å¤äºåéä¸­çæ°æ®
        int retryTimeOutCount = this.mcMailMapper.retryTimeOut(MailEnum.Flag.SENDING.getCode(), MailEnum.Flag.UNHANDLE.getCode(), now);
        LOGGER.info("retryTimeOutCount={}", retryTimeOutCount);
    }

    private boolean sendMail(MailMessageVO mailParam) {
//校验参数
        checkParam(mailParam);
        try {
            MimeMessagePreparator preparator = mimeMessage -> {
// è®¾ç½®utf-8é²æ­¢åºç°ä¹±ç 
                MimeMessageHelper message = new MimeMessageHelper(mimeMessage, TRUE, MailConts.UTF_8);
                String[] tos = new String[mailParam.getToMailList().size()];
                mailParam.getToMailList().toArray(tos);
                message.setTo(tos);
//æéäºº
                if (CollectionUtils.isNotEmpty(mailParam.getCcMailList())) {
                    String[] ccs = new String[mailParam.getCcMailList().size()];
                    mailParam.getCcMailList().toArray(ccs);
                    message.setCc(ccs);
                }
                message.setFrom(new InternetAddress(portalEmailProperties.getFrom()));
                message.setSubject(mailParam.getMailTitle());
                message.setText(mailParam.getMailText(), mailParam.isHtmlText());
//å¤çéä»¶éä»¶
                Map<String, InputStream> attachments = mailParam.getAttachments();
                if (MapUtils.isNotEmpty(attachments)) {
                    attachments.forEach((filenName, attachment) -> {
                        try {
                            message.addAttachment(filenName, new ByteArrayResource(IOUtils.toByteArray(attachment)));
                        } catch (Exception e) {
                            LOGGER.error("æ·»å éä»¶å¤±è´¥", e);
                            throw new BizException(ExceptionCodeEnum.SERVER_ERROR.code(), "æ·»å éä»¶å¤±è´¥");
                        }
                    });
                }
            };
            javaMailSender.send(preparator);
            LOGGER.info("mail send success");
        } catch (Exception e) {
            LOGGER.error("åéé®ä»¶å¤±è´¥", e);
            throw new BizException(ExceptionCodeEnum.SERVER_ERROR.code(), "send mail fail");
        } finally {
// å³é­æµ
            if (MapUtils.isNotEmpty(mailParam.getAttachments())) {
                mailParam.getAttachments().forEach((filenName, attachment) -> {
                    if (attachment != null) {
                        try {
                            attachment.close();
                        } catch (IOException e) {
                            LOGGER.error("å³é­æä»¶æµå¤±è´¥,filenName=" + filenName);
                        }
                    }
                });
            }
        }
        return true;
    }

    /**
     * (校验参数)
     *
     * @param mailParam
     */
    private void checkParam(MailMessageVO mailParam) {
        checkArgument(CollectionUtils.isEmpty(mailParam.getToMailList()), ExceptionCodeEnum.PARAM_ERROR.code(), "æ¥æ¶äººä¸è½ä¸ºç©º");
        checkArgument(Strings.isNullOrEmpty(mailParam.getMailTitle()), ExceptionCodeEnum.PARAM_ERROR.code(), "æ é¢ä¸è½ä¸ºç©º");
        checkArgument(Strings.isNullOrEmpty(mailParam.getMailText()), ExceptionCodeEnum.PARAM_ERROR.code(), "æ­£æä¸è½ä¸ºç©º");
    }

    /**
     * (å°éå·åéçå­ç¬¦æ¢è½¬æ¢ælist)
     *
     * @param str
     * @return
     */
    private List<String> str2List(String str) {
        List<String> list = Lists.newArrayList();
        String[] arr = str.split(",");
        for (String param : arr) {
            list.add(param);
        }
        return list;
    }

    /**
     * (listè½¬æ¢æå­ç¬¦ä¸²ï¼ç¨éå·åé)
     *
     * @param list
     * @return
     */
    private String str2List(List<String> list) {
        String result = "";
        StringBuilder sb = new StringBuilder("");
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(str -> {
                sb.append(",");
                sb.append(str);
            });
            result = sb.toString();
            result = sb.substring(1);
        }
        return result;
    }
}